package com.orifine.sql.simple;

import java.util.ArrayList;
import java.util.List;

class SimpleSql {
	private static final String AND = ") \nAND (";
	private static final String OR = ") \nOR (";
	
	public enum StatementType {
		DELETE, INSERT, SELECT, UPDATE
	}

	public StatementType statementType;
	public List<String> sets = new ArrayList<String>();
	public List<String> select = new ArrayList<String>();
	public List<String> tables = new ArrayList<String>();
	public List<String> join = new ArrayList<String>();
	public List<String> innerJoin = new ArrayList<String>();
	public List<String> outerJoin = new ArrayList<String>();
	public List<String> leftOuterJoin = new ArrayList<String>();
	public List<String> rightOuterJoin = new ArrayList<String>();
	public List<String> where = new ArrayList<String>();
	public List<String> having = new ArrayList<String>();
	public List<String> groupBy = new ArrayList<String>();
	public List<String> orderBy = new ArrayList<String>();
	public List<String> lastList = new ArrayList<String>();
	public List<String> columns = new ArrayList<String>();
	public List<String> values = new ArrayList<String>();
	public boolean distinct;
	public Integer offset;
	public Integer rows;

	private void sqlClause(StringBuilder builder, String keyword,
			List<String> parts, String open, String close, String conjunction) {
		if (!parts.isEmpty()) {
			if (builder.length() > 0)
				builder.append("\n");
			builder.append(keyword);
			builder.append(" ");
			builder.append(open);
			String last = "________";
			for (int i = 0, n = parts.size(); i < n; i++) {
				String part = parts.get(i);
				if (i > 0 && !part.equals(AND) && !part.equals(OR)
						&& !last.equals(AND) && !last.equals(OR)) {
					builder.append(conjunction);
				}
				builder.append(part);
				last = part;
			}
			builder.append(close);
		}
	}
	
	private void limitClause(StringBuilder builder){
		if (rows != null){
			if(builder.length() > 0) builder.append("\n");
			if(offset != null){
				builder.append("LIMIT").append(" ").append(offset).append(",").append(rows);
			} else {
				builder.append("LIMIT").append(" ").append(rows);
			}
		}
	}

	String selectSQL() {
		StringBuilder builder = new StringBuilder();
		if (distinct) {
			sqlClause(builder, "SELECT DISTINCT", select, "", "", ", ");
		} else {
			sqlClause(builder, "SELECT", select, "", "", ", ");
		}

		sqlClause(builder, "FROM", tables, "", "", ", ");
		sqlClause(builder, "JOIN", join, "", "", "JOIN");
		sqlClause(builder, "INNER JOIN", innerJoin, "", "", "\nINNER JOIN ");
		sqlClause(builder, "OUTER JOIN", outerJoin, "", "", "\nOUTER JOIN ");
		sqlClause(builder, "LEFT OUTER JOIN", leftOuterJoin, "", "",
				"\nLEFT OUTER JOIN ");
		sqlClause(builder, "RIGHT OUTER JOIN", rightOuterJoin, "", "",
				"\nRIGHT OUTER JOIN ");
		sqlClause(builder, "WHERE", where, "(", ")", " AND ");
		sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
		sqlClause(builder, "HAVING", having, "(", ")", " AND ");
		sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
		limitClause(builder);
		return builder.toString();
	}

	String insertSQL() {
		StringBuilder builder = new StringBuilder();

		sqlClause(builder, "INSERT INTO", tables, "", "", "");
		sqlClause(builder, "", columns, "(", ")", ", ");
		sqlClause(builder, "VALUES", values, "(", ")", ", ");
		return builder.toString();
	}

	String deleteSQL() {
		StringBuilder builder = new StringBuilder();

		sqlClause(builder, "DELETE FROM", tables, "", "", "");
		sqlClause(builder, "WHERE", where, "(", ")", " AND ");
		return builder.toString();
	}

	String updateSQL() {
		StringBuilder builder = new StringBuilder();

		sqlClause(builder, "UPDATE", tables, "", "", "");
		sqlClause(builder, "SET", sets, "", "", ", ");
		sqlClause(builder, "WHERE", where, "(", ")", " AND ");
		return builder.toString();
	}

	public String sql() {
		if (statementType == null) {
			return null;
		}

		String answer;

		switch (statementType) {
		case DELETE:
			answer = deleteSQL();
			break;

		case INSERT:
			answer = insertSQL();
			break;

		case SELECT:
			answer = selectSQL();
			break;

		case UPDATE:
			answer = updateSQL();
			break;

		default:
			answer = null;
		}

		return answer;
	}
}
